package com.leosoft.heatmonitor.dao;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;

import com.leosoft.heatmonitor.model.Device;
import com.leosoft.heatmonitor.model.Project;
import com.leosoft.heatmonitor.model.Target;

@Component
public class DeviceDAO extends BaseDAO {
	SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	public Map<String, Object> list(int startIndex, int length, List<String[]> wherePart, List<String[]> odrerPart,
			String userId) {
		Object total = new Object();
		Criteria c = this.getSession().createCriteria(Device.class);
		if (!userId.isEmpty()) {
			c = c.createCriteria("project");
			c = c.createCriteria("users");
			c = c.add(Restrictions.eq("id", userId));
			c.setCacheable(true);
			c.setProjection(Projections.rowCount());
			total = c.uniqueResult();
			c = this.getSession().createCriteria(Device.class);
			c.setProjection(Projections.rowCount());
		} else {
			c.setCacheable(true);
			c.setProjection(Projections.rowCount());
			total = c.uniqueResult();
		}

		for (String[] order : odrerPart) {
			if (!order[0].equals("projectName")) {
				if (order[1].equals("desc")) {
					c.addOrder(Order.desc(order[0]));
				} else {
					c.addOrder(Order.asc(order[0]));
				}
			}
		}
		for (String[] where : wherePart) {
			if (!where[0].equals("projectName")) {
				c = c.add(Restrictions.sqlRestriction("{alias}." + where[0] + " LIKE '%" + where[1] + "%'"));
			}
		}
		c = c.createCriteria("project");
		for (String[] order : odrerPart) {
			if (order[0].equals("projectName")) {
				if (order[1].equals("desc")) {
					c.addOrder(Order.desc("name"));
				} else {
					c.addOrder(Order.asc("name"));
				}
			}
		}
		for (String[] where : wherePart) {
			if (where[0].equals("projectName")) {
				c = c.add(Restrictions.like("name", where[1], MatchMode.ANYWHERE));
			}
		}
		if (!userId.isEmpty()) {
			c = c.createCriteria("users");
			c = c.add(Restrictions.eq("id", userId));
		}
		Object recordsFiltered = c.uniqueResult();
		c.setProjection(null);
		c.setFirstResult(startIndex);
		c.setMaxResults(length);
		List<Device> devices = c.list();
		List<Map<String, Object>> dataResults = new ArrayList<>();
		for (Device device : devices) {
			synchronized (format) {
				String createTime = format.format(device.getCreateTime());
				String updateTime = format.format(device.getUpdateTime());
				Map<String, Object> data = new HashMap<>();
				data.put("projectId", device.getProject().getId());
				data.put("name", device.getName());
				data.put("projectName", device.getProject().getName());
				data.put("key", device.getKey());
				data.put("type", device.getType());
				data.put("createTime", createTime);
				data.put("format", device.getFormat());
				data.put("updateTime", updateTime);
				Calendar ca = Calendar.getInstance();
				ca.setTime(device.getUpdateTime());
				ca.set(Calendar.MINUTE, 0);
				ca.set(Calendar.SECOND, 0);
				Calendar now = Calendar.getInstance();
				now.set(Calendar.MINUTE, 0);
				now.set(Calendar.SECOND, 0);
				long hours = (now.getTime().getTime() - ca.getTime().getTime()) / (1000 * 60 * 60);
				if (hours >= 2) {
					data.put("status", 1);
				} else {
					data.put("status", 0);
				}
				List<Target> targets = device.getTargets();
				if (!targets.isEmpty()) {
					StringBuilder targetIds = new StringBuilder();
					StringBuilder targetNames = new StringBuilder();

					for (Target target : targets) {
						targetIds.append(target.getId());
						targetIds.append(",");
						targetNames.append(target.getBuilding());
						targetNames.append(target.getDoor());
						targetNames.append(target.getUser());
						targetNames.append(",");
					}
					String targetString = targetIds.substring(0, targetIds.length() - 1);
					String targetNameString = targetNames.substring(0, targetNames.length() - 1);
					data.put("targetIds", targetString);
					data.put("targetNames", targetNameString);
				} else {
					data.put("targetIds", null);
					data.put("targetNames", null);
				}

				data.put("id", device.getId());
				dataResults.add(data);
			}

		}

		Map<String, Object> result = new HashMap<String, Object>();
		result.put("recordsTotal", total);
		result.put("recordsFiltered", recordsFiltered);
		result.put("data", dataResults);
		return result;
	}

	public boolean notExist(String projectId, String key) {
		Criteria c = this.getSession().createCriteria(Device.class);
		c = c.add(Restrictions.like("key", key));
		c = c.createCriteria("project");
		c = c.add(Restrictions.eq("id", projectId));
		return c.list().isEmpty();

	}

	public void create(Project project, String name, String key, String type, String format2, List<Target> targets) {
		Device device = new Device();
		device.setName(name);
		device.setFormat(format2);
		device.setKey(key);
		device.setProject(project);
		device.setTargets(targets);
		device.setType(type);
		device.setCreateTime(new Timestamp(System.currentTimeMillis()));
		device.setUpdateTime(new Timestamp(0));
		this.getSession().merge(device);
	}

	public Device getDeviceById(String id) {
		Criteria c = this.getSession().createCriteria(Device.class);
		c = c.add(Restrictions.like("id", id));
		return (Device) c.uniqueResult();
	}

	public void delete(String id) {
		Device device = getDeviceById(id);
		this.getSession().delete(device);
		SQLQuery q3 = this.getSession().createSQLQuery(
				"delete from devicetarget where device_id not in(select id from device)");
		q3.executeUpdate();
	}

	public void update(String id, Project project, String name, String key, String type, String format2,
			List<Target> targets) {
		Device device = getDeviceById(id);
		device.setName(name);
		device.setFormat(format2);
		device.setKey(key);
		device.setProject(project);
		device.setTargets(targets);
		device.setType(type);
		this.getSession().merge(device);
	}

	public List<String> loadDevice(String projectId) {
		Criteria c = this.getSession().createCriteria(Device.class);
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.groupProperty("key"));
		c = c.setProjection(projectionList);
		c = c.createCriteria("project");
		c = c.add(Restrictions.eq("id", projectId));
		return c.list();
	}

	public Device getDeviceByKey(String deviceKey) {
		Criteria c = this.getSession().createCriteria(Device.class);
		c = c.add(Restrictions.eq("key", deviceKey));
		return (Device) c.uniqueResult();
	}
}
